package com.fishingwithme.infrastructure.utils;

import com.fishingwithme.domain.common.Location;
import com.fishingwithme.infrastructure.CodeEnum;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

public class CommonUtils {
    public static final ObjectMapper objectMapper = new ObjectMapper();
    public static final Integer SPOT_DEFAULT_DISTANCE = 20;
    public static final Integer DEFAULT_CIRCLE_DISTANCE = 100000000;
    private static final Logger logger = LoggerFactory.getLogger(CommonUtils.class);

    public static String CODE_VERIFY_EMAIL = "VERIFY_EMAIL";


    public static Integer generateRandomNumber() {
        return ThreadLocalRandom.current().nextInt(100000, 1000000);
    }

    public static String generateRandomString(int length, int complexity) {
        // 定义不同类型的字符集
        String upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
        String numbers = "0123456789";
        String specialCharacters = "!@#$%^&*()-_=+[]{}|;:'\",.<>/?";

        // 根据复杂度组合字符集
        StringBuilder allowedCharacters = new StringBuilder();
        switch (complexity) {
            case 1:
                allowedCharacters.append(upperCaseLetters).append(lowerCaseLetters);
                break;
            case 2:
                allowedCharacters.append(upperCaseLetters).append(lowerCaseLetters).append(numbers);
                break;
            case 3:
                allowedCharacters.append(upperCaseLetters).append(lowerCaseLetters)
                        .append(numbers).append(specialCharacters);
                break;
            default:
                throw new IllegalArgumentException("不支持的复杂度级别: " + complexity);
        }

        // 使用SecureRandom生成更安全的随机数
        Random random = new Random();
        StringBuilder password = new StringBuilder();

        // 确保生成的密码包含至少一个每种类型的字符(如果适用)
        if (complexity >= 2) {
            // 至少包含一个数字
            password.append(numbers.charAt(random.nextInt(numbers.length())));
        }

        if (complexity >= 3) {
            // 至少包含一个特殊字符
            password.append(specialCharacters.charAt(random.nextInt(specialCharacters.length())));
        }

        // 生成剩余的字符
        int remainingLength = length - password.length();
        for (int i = 0; i < remainingLength; i++) {
            int randomIndex = random.nextInt(allowedCharacters.length());
            password.append(allowedCharacters.charAt(randomIndex));
        }

        // 打乱密码顺序，提高随机性
        return shuffleString(password.toString());
    }

    // 打乱字符串顺序
    private static String shuffleString(String input) {
        char[] characters = input.toCharArray();
        Random random = new Random();

        for (int i = characters.length - 1; i > 0; i--) {
            int randomIndex = random.nextInt(i + 1);
            char temp = characters[i];
            characters[i] = characters[randomIndex];
            characters[randomIndex] = temp;
        }

        return new String(characters);
    }

    public static GeocoderResponse getGeocoder(TencentGeocoderClient geocoderClient, Location location) {
        GeocoderResponse reverseResp;
        try {
            reverseResp = geocoderClient.reverse(location.getLatitude(), location.getLongitude());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (reverseResp.getStatus() == 0) {
            System.out.println("\n反向编码结果：");
            logger.info(Objects.toString(reverseResp));
        } else {
            throw new RuntimeException("获取定位点失败.");
        }
        return reverseResp;
    }

    public static <T, M> List<T> convert(String json, Class<M> clazz) {
        if (json == null || json.trim().isEmpty()) {
            return List.of(); // 空输入返回空列表（或返回 null，根据需求调整）
        }
        try {
            if (clazz.isEnum()) {
                // 处理枚举列表
                List<JsonNode> enumValues = objectMapper.readValue(json, new TypeReference<>() {
                });
                return enumValues.stream()
                        .map(value -> {
                            Enum en;
                            if (value.has("code")) {
                                String code = value.get("code").asText();
                                en = Enum.valueOf((Class) clazz, code);
                            } else {
                                en = Enum.valueOf((Class) clazz, value.asText());
                            }
                            CodeEnum ce = (CodeEnum) en;
                            try {
                                return ce.toJson();
                            } catch (JSONException e) {
                                throw new RuntimeException(e);
                            }
                        })
                        .map(obj -> (T) obj)
                        .collect(Collectors.toList());
            } else {
                // 处理普通对象列表
                TypeReference<List<T>> typeReference = new TypeReference<>() {
                };
                return objectMapper.readValue(json, typeReference);
            }
        } catch (Exception e) {
            throw new RuntimeException(
                    String.format("Failed to convert JSON to List<%s>: %s", clazz.getName(), e.getMessage()),
                    e
            );
        }

    }

    public static Long getUserId() {
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return Long.valueOf(userDetails.getUsername());
    }

    public static String thdSession(String sessionKey, String openId) {
        StringBuilder sb = new StringBuilder();
        sb.append(sessionKey).append("_").append(openId);
        return sb.toString();
    }

    public static List<JSONObject> getEnumProps(Class<? extends Enum<?>> enumClass) throws JSONException {
        // 获取枚举的所有实例
        Enum<?>[] enumConstants = enumClass.getEnumConstants();
        List<JSONObject> enums = new ArrayList<>();

        // 遍历每个枚举实例
        for (Enum<?> enumConstant : enumConstants) {
            JSONObject enumProps = new JSONObject();

            // 添加枚举名称
            enumProps.put("name", enumConstant.name());

            // 获取并添加枚举的字段值
            Field[] declaredFields = enumClass.getDeclaredFields();
            for (Field field : declaredFields) {
                if (!java.lang.reflect.Modifier.isStatic(field.getModifiers()) &&
                        !field.isSynthetic() &&
                        !field.getName().equals("$VALUES")) {
                    try {
                        field.setAccessible(true);
                        // 检查字段是否有JSONField注解
                        String fieldName = field.getName();
                        JsonProperty jsonField = field.getAnnotation(JsonProperty.class);
                        if (jsonField != null && !jsonField.value().isEmpty()) {
                            fieldName = jsonField.value();
                        }
                        enumProps.put(fieldName, field.get(enumConstant));
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            enums.add(enumProps);
        }
        return enums;

    }

    public static Date now() {
        return Calendar.getInstance().getTime();
    }

    public static String today() {
        LocalDate today = now().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return today.format(formatter); // 结果："2025-08-20"

    }
}
